home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / games / 65 / pascal / spheres.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1986-10-16  |  8.8 KB  |  435 lines

  1. program spheres;
  2.  
  3. {
  4. This program draws spheres of various sizes on the graphics screen.
  5. }
  6.  
  7. const
  8.   {$i gemconst.pas}
  9.   maxx        = 639;
  10.   minx        =   0;
  11.   maxy        = 399;
  12.   miny        =   0;
  13.   white_color =   0;
  14.   black_color =   1;
  15.  
  16.   pi = 3.141592654;
  17.  
  18. type
  19.   {$i gemtype.pas}
  20.   mode_type = (draw, erase);
  21.  
  22. var
  23.   plotting_window : integer;
  24.   quit            : boolean;
  25.  
  26.  
  27. {$i gemsubs.pas}
  28.  
  29.  
  30. procedure start_graphics(var plotting_window : integer);
  31.  
  32. {
  33. Set up and clear a plotting window.
  34. }
  35.  
  36. var
  37.   null_string : string;
  38.  
  39. begin
  40.  
  41.   null_string := '';
  42.  
  43.   hide_mouse;
  44.  
  45.   plotting_window := new_window(0, null_string, 0, 0, maxx + 1, maxy + 1);
  46.   open_window(plotting_window, 0, 0, maxx + 1, maxy + 1);
  47.  
  48.   paint_color(white_color);
  49.   paint_rect(0, 0, maxx + 1, maxy + 1);
  50.   line_color(black_color);
  51.  
  52. end;
  53.  
  54.  
  55. procedure stop_graphics(plotting_window : integer);
  56.  
  57. {
  58. Delete plotting window.
  59. }
  60.  
  61. begin
  62.  
  63.   close_window(plotting_window);
  64.   delete_window(plotting_window);
  65.  
  66.   show_mouse;
  67.  
  68. end;
  69.  
  70.  
  71. function point_in_range(x, y : integer) : boolean;
  72.  
  73. {
  74. Return true only when point (x, y) is on the screen.
  75. }
  76.  
  77. begin
  78.  
  79.   point_in_range := (x >= 0) and (x <= maxx) and
  80.                     (y >= 0) and (y <= maxy);
  81.  
  82. end;
  83.  
  84.  
  85. procedure point(x, y : integer);
  86.  
  87. {
  88. Plot a point on the screen if it is in range.
  89. }
  90.  
  91. begin
  92.  
  93.   if point_in_range(x, y)
  94.     then plot(x, maxy - y);
  95.  
  96. end;
  97.  
  98.  
  99. function min(a, b : integer) : integer;
  100.  
  101. {
  102. Return the lesser of a and b.
  103. }
  104.  
  105. begin
  106.  
  107.   if a < b
  108.     then min := a
  109.     else min := b;
  110.  
  111. end;
  112.  
  113.  
  114. function max(a, b : integer) : integer;
  115.  
  116. {
  117. Return the greater of a and b.
  118. }
  119.  
  120. begin
  121.  
  122.   if a > b
  123.     then max := a
  124.     else max := b;
  125.  
  126. end;
  127.  
  128.  
  129. procedure draw_line(x0, y0, x1, y1 : integer; draw_mode : mode_type);
  130.  
  131. {
  132. Draw or erase a line on the screen if at least one point is within the
  133. boundries of the screen.
  134. }
  135.  
  136. begin
  137.  
  138.   if point_in_range(x0, y0) or point_in_range(x1, y1)
  139.     then begin
  140.  
  141.       x0 := max(x0, 0);
  142.       y0 := max(y0, 0);
  143.       x1 := max(x1, 0);
  144.       y1 := max(y1, 0);
  145.  
  146.       x0 := min(x0, maxx);
  147.       y0 := min(y0, maxy);
  148.       x1 := min(x1, maxx);
  149.       y1 := min(y1, maxy);
  150.  
  151.       if draw_mode = erase
  152.         then line_color(white_color);
  153.  
  154.       line(x0, maxy - y0, x1, maxy - y1);
  155.  
  156.       if draw_mode = erase
  157.         then line_color(black_color);
  158.  
  159.     end;
  160.  
  161. end;
  162.  
  163.  
  164. function mouse_button_pressed : boolean;
  165.  
  166. {
  167. Return true when the left mouse button is depressed (false otherwise).  Do
  168. not wait for button to be pressed.
  169. }
  170.  
  171. const
  172.   left_button = $0001;
  173.   button_down = $0001;
  174.  
  175. var
  176.   event,
  177.   discard      : integer;
  178.   message_area : message_buffer;
  179.  
  180. begin
  181.  
  182.   event := get_event(e_button | e_timer, left_button, button_down, 0, 0,
  183.                      false, 0, 0, 0, 0, false, 0, 0, 0, 0,
  184.                      message_area, discard, discard, discard,
  185.                      discard, discard, discard);
  186.  
  187.   mouse_button_pressed := (event & e_button) <> 0;
  188.  
  189. end;
  190.  
  191.  
  192. function random(low_value, high_value : integer) : integer;
  193.  
  194. {
  195. Return a pseudorandom integer between low_value and high_value (inclusive).
  196. Low value must be less than high value.
  197. }
  198.  
  199.  
  200.   function random_24_bit : long_integer;
  201.  
  202.   {
  203.   Return 24 bit pseudorandom integer.
  204.   }
  205.  
  206.   xbios(17);
  207.  
  208.  
  209. begin
  210.  
  211.   random := int(low_value + (random_24_bit mod (high_value - low_value + 1)));
  212.  
  213. end;
  214.  
  215.  
  216. procedure calc_y(x, z, radius : real; var result : real;
  217.                               var valid_args : boolean);
  218.  
  219. {
  220. Given the x and z coordinate and the radius of a circle, this procedure
  221. returns the value of y.  If there is no value of y for the given arguements,
  222. valid arguements is false.
  223. }
  224.  
  225. var
  226.   y_squared : real;
  227.  
  228. begin
  229.  
  230.   y_squared := sqr(radius) - sqr(x) - sqr(z);
  231.  
  232.   valid_args := true;
  233.  
  234.   if y_squared >= 0.0
  235.     then result := sqrt(y_squared)
  236.     else valid_args := false;
  237.  
  238. end;
  239.  
  240.  
  241. procedure y_rotation(var x, z : real; angle : real);
  242.  
  243. {
  244. Rotate a point about the y axis.
  245. }
  246.  
  247. var
  248.   temp_x,
  249.   sin_angle,
  250.   cos_angle : real;
  251.  
  252. begin
  253.  
  254.   { Compute these values only once. }
  255.   sin_angle := sin(angle);
  256.   cos_angle := cos(angle);
  257.  
  258.   temp_x := x *   cos_angle  + z * sin_angle;
  259.   z      := x * (-sin_angle) + z * cos_angle;
  260.  
  261.   x := temp_x;
  262.  
  263. end;
  264.  
  265.  
  266. procedure draw_sphere(plotting_window : integer; radius, x_center, y_center,
  267.                                  rotation_angle : real; var quit : boolean);
  268.  
  269. {
  270. Draw a wire-frame sphere rotated about the y axis.  The center
  271. of the sphere prior to rotation is (x_center, y_center).
  272. }
  273.  
  274. const
  275.   z_delta = 4.0;
  276.  
  277. var
  278.   x,
  279.   z,
  280.   plot_x,
  281.   plot_y,
  282.   plot_z     : real;
  283.   valid_args : boolean;
  284.  
  285. begin
  286.  
  287.   z := -radius;
  288.  
  289.   quit := false;
  290.  
  291.   while (z <= radius) and not quit do begin
  292.  
  293.     x := -radius;
  294.  
  295.     while x <= radius do begin
  296.  
  297.       plot_x := x;
  298.       plot_z := z;
  299.  
  300.       calc_y(plot_x, plot_z, radius, plot_y, valid_args);
  301.  
  302.       if valid_args
  303.         then begin
  304.  
  305.           y_rotation(plot_x, plot_z, rotation_angle);
  306.  
  307.           { Hide lines if drawing the front of a sphere. }
  308.           if plot_z >= 0.0
  309.             then draw_line(round(plot_x + x_center), round( plot_y + y_center),
  310.                            round(plot_x + x_center), round(-plot_y + y_center),
  311.                                                                         erase);
  312.  
  313.           point(round(plot_x + x_center), round( plot_y + y_center));
  314.           point(round(plot_x + x_center), round(-plot_y + y_center));
  315.  
  316.         end;
  317.  
  318.       x := x + 1.0;
  319.  
  320.     end;
  321.  
  322.     quit := mouse_button_pressed;
  323.     z := z + z_delta;
  324.  
  325.   end;
  326.  
  327. end;
  328.  
  329.  
  330. procedure introduce_program;
  331.  
  332. {
  333. Introduce the program with a dialog box.
  334. }
  335.  
  336. const
  337.   { Width (in characters) of dialog box }
  338.   box_width = 64;
  339.   color     = $1180;
  340.  
  341.   { Strings that will be inserted into dialog box. }
  342.   str_1     = 'Spheres 1.0 - A Graphics Demo Program';
  343.   str_2     = 'Written by Eric Bergman-Terrell';
  344.   str_3     = 'of Cadenza Software, Ltd.';
  345.   str_4     = '1704 Imperial Ridge, Las Cruces, NM  88001, USA';
  346.   str_5     = 'Portions of this product are copyright (c) 1986, OSS and CCD';
  347.   str_6     = 'Used by Permission of OSS';
  348.   str_7     = 'This software has been placed in the public domain.';
  349.   str_8     = 'Hold down left mouse button to quit.';
  350.   start_str = 'BEGIN';
  351.  
  352. var
  353.   intro_box     : dialog_ptr;
  354.   line_1,
  355.   line_2,
  356.   line_3,
  357.   line_4,
  358.   line_5,
  359.   line_6,
  360.   line_7,
  361.   line_8,
  362.   start_button,
  363.   button_pushed : integer;
  364.   start_item    : tree_index;
  365.  
  366. begin
  367.  
  368.   { Set up the mouse the be an arrow. }
  369.   init_mouse;
  370.   set_mouse(m_arrow);
  371.  
  372.   { Get a dialog box. }
  373.   intro_box := new_dialog(8, 0, 0, box_width, 18);
  374.  
  375.   { Insert strings into dialog box. }
  376.   line_1 := add_ditem(intro_box, g_text, none, 1, 1, box_width, 1, 0, color);
  377.   line_2 := add_ditem(intro_box, g_text, none, 1, 3, box_width, 1, 0, color);
  378.   line_3 := add_ditem(intro_box, g_text, none, 1, 4, box_width, 1, 0, color);
  379.   line_4 := add_ditem(intro_box, g_text, none, 1, 5, box_width, 1, 0, color);
  380.   line_5 := add_ditem(intro_box, g_text, none, 1, 7, box_width, 1, 0, color);
  381.   line_6 := add_ditem(intro_box, g_text, none, 1, 8, box_width, 1, 0, color);
  382.   line_7 := add_ditem(intro_box, g_text, none, 1, 11, box_width, 1, 0, color);
  383.   line_8 := add_ditem(intro_box, g_text, none, 1, 13, box_width, 1, 0, color);
  384.   start_button := add_ditem(intro_box, g_button,
  385.                             exit_btn | selectable | default,
  386.                             30, 16, length(start_str), 1, 0, color);
  387.  
  388.   { Adjust the strings in the dialog box. }
  389.   set_dtext(intro_box, line_1, str_1, system_font, te_center);
  390.   set_dtext(intro_box, line_2, str_2, system_font, te_center);
  391.   set_dtext(intro_box, line_3, str_3, system_font, te_center);
  392.   set_dtext(intro_box, line_4, str_4, system_font, te_center);
  393.   set_dtext(intro_box, line_5, str_5, system_font, te_center);
  394.   set_dtext(intro_box, line_6, str_6, system_font, te_center);
  395.   set_dtext(intro_box, line_7, str_7, system_font, te_center);
  396.   set_dtext(intro_box, line_8, str_8, system_font, te_center);
  397.   set_dtext(intro_box, start_button, start_str, system_font, te_center);
  398.  
  399.   center_dialog(intro_box);
  400.  
  401.   { Introduce the program. }
  402.   button_pushed := do_dialog(intro_box, start_item);
  403.  
  404.   end_dialog(intro_box);
  405.   delete_dialog(intro_box);
  406.  
  407. end;
  408.  
  409.  
  410. begin
  411.  
  412.   if init_gem >= 0
  413.     then begin
  414.  
  415.       introduce_program;
  416.  
  417.       { Prepare to plot. }
  418.       start_graphics(plotting_window);
  419.  
  420.       repeat
  421.  
  422.         draw_sphere(plotting_window, random(20, (maxx + 1) div 6),
  423.                                  random(0, maxx), random(0, maxy),
  424.                                 pi * (random(0, 25) / 100), quit);
  425.  
  426.       until quit;
  427.  
  428.       stop_graphics(plotting_window);
  429.  
  430.       exit_gem;
  431.  
  432.     end;
  433.  
  434. end.
  435.